Skip to content

Conversation

@Roel4990
Copy link
Member

@Roel4990 Roel4990 commented Oct 29, 2025

Related issue 🛠

Work Description ✏️

  • 탐색 뷰 바텀시트에서 리스트 검색 클릭 시 데이터

Screenshot 📸

이미지는 없습니다.

To Reviewers 📢

Summary by CodeRabbit

릴리스 노트

  • 버그 수정
    • 탐색 탭에서 필터 적용 기능을 개선했습니다. 카테고리, 지역, 연령대 필터의 처리 로직을 최적화하여 더욱 안정적인 필터링 경험을 제공합니다.

✏️ Tip: You can customize this high-level summary in your review settings.

@Roel4990 Roel4990 self-assigned this Oct 29, 2025
@Roel4990 Roel4990 requested a review from a team as a code owner October 29, 2025 04:31
@Roel4990 Roel4990 requested review from Hyobeen-Park, angryPodo and chattymin and removed request for a team October 29, 2025 04:32
@Roel4990 Roel4990 added 🧡세홍🧡 🧡세홍🧡 FEAT✨ 새로운 기능 구현 labels Oct 29, 2025
@Roel4990 Roel4990 linked an issue Oct 29, 2025 that may be closed by this pull request
1 task
@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

개요

ExploreFilterSection.kt의 onSave 함수에서 필터 적용 시 Mixpanel 분석 이벤트를 추가했습니다. 임시 필터 상태에서 카테고리, 지역, 연령대 필터를 구성하고 로컬 리뷰 활성화 여부를 확인한 후, filterApplied 이벤트를 기록합니다.

변경 사항

코호트 / 파일 변경 요약
필터 분석 추적 추가
app/src/main/java/com/spoony/spoony/presentation/explore/component/ExploreFilterSection.kt
onSave 함수에서 필터 적용 시 tracker.commonEvents.filterApplied 분석 이벤트를 발행하는 로직 추가. 카테고리, 지역, 연령대 필터 목록과 로컬 리뷰 활성화 여부를 구성하여 "explore" 페이지에서의 필터 적용을 추적.

시퀀스 다이어그램

sequenceDiagram
    participant User
    participant ExploreFilterSection
    participant Analytics as Mixpanel Tracker
    participant FilterApply

    User->>ExploreFilterSection: Save 클릭 (onSave)
    ExploreFilterSection->>ExploreFilterSection: 임시 필터 상태에서<br/>필터 목록 구성
    alt 필터 적용됨 또는 로컬 리뷰 활성화
        ExploreFilterSection->>Analytics: filterApplied 이벤트 발행<br/>(pageApplied, filters, localReview)
        Analytics-->>ExploreFilterSection: 이벤트 기록 완료
    end
    ExploreFilterSection->>FilterApply: ApplyFilter 실행
    FilterApply-->>User: 필터 적용 완료
Loading

코드 리뷰 예상 소요 시간

🎯 2 (단순) | ⏱️ ~8분

  • 필터 상태에서 분석 데이터 구성 로직 검증
  • Mixpanel 이벤트 파라미터 정확성 확인
  • 기존 ApplyFilter 흐름에 영향 없음 확인

추천 검토자

  • chattymin
  • angryPodo

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Description check ❓ Inconclusive PR 설명이 템플릿 구조를 따르고 있으나, 'Work Description' 섹션이 불완전합니다. '탐색 뷰 바텀시트에서 리스트 검색 클릭 시 데이터'는 문장이 완결되지 않았습니다. Work Description 섹션을 완성하여 Mixpanel 이벤트 추적의 구체적인 내용(어떤 필터 상태, 어떤 이벤트 데이터가 추적되는지)을 명확히 설명해 주세요.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed 제목이 PR의 주요 변경사항을 명확하게 설명합니다. ExploreFilterSection에 Mixpanel 분석 이벤트 추적이 추가되었으며, 제목 '[FEAT/#424] 탐색 뷰 믹스패널 붙이기'는 이를 정확히 반영합니다.
Linked Issues check ✅ Passed 코드 변경사항(ExploreFilterSection.kt에서 filterApplied 이벤트 추적 추가)이 issue #424의 주요 목표인 '탐색 뷰에 믹스패널 붙이기'를 충족합니다.
Out of Scope Changes check ✅ Passed 모든 변경사항이 issue #424 범위 내에 있습니다. ExploreFilterSection.kt의 수정사항은 탐색 뷰에 Mixpanel 분석 붙이기라는 목표와 직접 관련이 있으며, 범위를 벗어난 변경은 없습니다.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/#424-explore-mixpanel

Tip

📝 Customizable high-level summaries are now available in beta!

You can now customize how CodeRabbit generates the high-level summary in your pull requests — including its content, structure, tone, and formatting.

  • Provide your own instructions using the high_level_summary_instructions setting.
  • Format the summary however you like (bullet lists, tables, multi-section layouts, contributor stats, etc.).
  • Use high_level_summary_in_walkthrough to move the summary from the description to the walkthrough section.

Example instruction:

"Divide the high-level summary into five sections:

  1. 📝 Description — Summarize the main change in 50–60 words, explaining what was done.
  2. 📓 References — List relevant issues, discussions, documentation, or related PRs.
  3. 📦 Dependencies & Requirements — Mention any new/updated dependencies, environment variable changes, or configuration updates.
  4. 📊 Contributor Summary — Include a Markdown table showing contributions:
    | Contributor | Lines Added | Lines Removed | Files Changed |
  5. ✔️ Additional Notes — Add any extra reviewer context.
    Keep each section concise (under 200 words) and use bullet or numbered lists for clarity."

Note: This feature is currently in beta for Pro-tier users, and pricing will be announced later.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/src/main/java/com/spoony/spoony/core/analytics/events/ExploreEvents.kt (1)

32-45: 필터 데이터를 JSONArray로 명시적 변환을 고려하세요.

List<String>JSONObject.put()에 직접 전달하면 동작은 하지만, JSON 배열로 명시적 변환하는 것이 더 명확하고 일관된 직렬화를 보장합니다.

다음 diff를 적용하여 명시적으로 JSONArray로 변환하세요:

 fun exploreFilterApplied(
     categoryFilters: List<String>,
     regionFilters: List<String>,
     ageGroupFilters: List<String>
 ) {
     tracker.track(
         eventName = "explore_filter_applied",
         properties = JSONObject().apply {
-            put("category_filters", categoryFilters)
-            put("region_filters", regionFilters)
-            put("age_group_filters", ageGroupFilters)
+            put("category_filters", JSONArray(categoryFilters))
+            put("region_filters", JSONArray(regionFilters))
+            put("age_group_filters", JSONArray(ageGroupFilters))
         }
     )
 }
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4baea67 and 56565ec.

📒 Files selected for processing (2)
  • app/src/main/java/com/spoony/spoony/core/analytics/events/ExploreEvents.kt (1 hunks)
  • app/src/main/java/com/spoony/spoony/presentation/explore/component/ExploreFilterSection.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: PR Builder
🔇 Additional comments (1)
app/src/main/java/com/spoony/spoony/presentation/explore/component/ExploreFilterSection.kt (1)

90-93: 필터 수집 로직이 올바릅니다.

tempFilterStatefilterItems에서 활성화된 필터들을 정확하게 추출하고 있습니다.

Copy link
Collaborator

@Hyobeen-Park Hyobeen-Park left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

리뷰가 너무 늦어졌네요.. 죄송합니다ㅠㅠ
이벤트 심는거 도와주셔서 감사해요!! 리뷰 남긴 것만 한 번 더 확인 부탁드립니다😊

Comment on lines 32 to 45
fun exploreFilterApplied(
categoryFilters: List<String>,
regionFilters: List<String>,
ageGroupFilters: List<String>
) {
tracker.track(
eventName = "explore_filter_applied",
properties = JSONObject().apply {
put("category_filters", categoryFilters)
put("region_filters", regionFilters)
put("age_group_filters", ageGroupFilters)
}
)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요거 이미 함수는 만들어져있어서 commonEvents 내에 있는 함수로 사용 부탁드립니다!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정했습니다!

Comment on lines 95 to 106
tracker.commonEvents.filterApplied(
pageApplied = "explore",
localReviewFilter = isLocalReviewEnabled
)

if (categoryFilters.isNotEmpty() || regionFilters.isNotEmpty() || ageGroupFilters.isNotEmpty()) {
tracker.exploreEvents.exploreFilterApplied(
categoryFilters = categoryFilters,
regionFilters = regionFilters,
ageGroupFilters = ageGroupFilters
)
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

요렇게 하면 이벤트가 2개 심겨요!! 위에도 말씀드렸지만 이미 만들어져있는 commonEvents.filterApplied로 심어주세요..!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수정했습니다!

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7cb52cc and 0c312d1.

📒 Files selected for processing (1)
  • app/src/main/java/com/spoony/spoony/presentation/explore/component/ExploreFilterSection.kt (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: PR Builder
  • GitHub Check: ktLint Checker
🔇 Additional comments (2)
app/src/main/java/com/spoony/spoony/presentation/explore/component/ExploreFilterSection.kt (2)

90-92: 필터 추출 로직이 올바릅니다.

카테고리, 지역, 연령 필터를 tempFilterState에서 선택된 항목만 추출하여 이름 리스트로 변환하는 로직이 정확합니다.


95-103: 믹스패널 이벤트 로깅이 올바르게 구현되었습니다.

commonEvents.filterApplied를 사용하여 필터 적용 이벤트를 추적하는 로직이 정확합니다. 과거 리뷰 코멘트에서 Hyobeen-Park님이 요청하신 대로 commonEvents.filterApplied를 사용하고 있으며, 중복 이벤트 없이 바텀시트 저장 시점에만 로깅됩니다.

참고: 조건문에 isLocalReviewEnabled가 포함되어 있어, 카테고리/지역/연령 필터 없이 로컬 리뷰만 활성화된 경우에도 이벤트가 로깅됩니다(이 경우 필터 배열은 비어있음). 이는 사용자가 바텀시트를 통해 로컬 리뷰만 변경하는 경우도 추적하기 위한 의도된 동작으로 보입니다.

val categoryFilters = filterItems.categories.filter { tempFilterState.categories[it.id] == true }.map { it.name }
val regionFilters = filterItems.regions.filter { tempFilterState.regions[it.id] == true }.map { it.name }
val ageGroupFilters = filterItems.ages.filter { tempFilterState.ages[it.id] == true }.map { it.name }
val isLocalReviewEnabled = filterItems.properties.firstOrNull()?.let { tempFilterState.properties[it.id] == true } ?: false
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

firstOrNull()을 사용한 방식이 취약할 수 있습니다.

현재 코드는 properties의 첫 번째 항목이 로컬 리뷰라고 가정하고 있습니다. 만약 속성의 순서가 변경되거나 로컬 리뷰 앞에 다른 속성이 추가되면 조용히 오동작할 수 있습니다.

Line 110에서 FilterCategory.LOCAL_REVIEW enum을 사용하는 것을 보면, 위치가 아닌 타입/카테고리로 로컬 리뷰 속성을 식별하는 방식이 더 안전할 것 같습니다.

다음과 같이 개선하는 것을 고려해보세요:

val isLocalReviewEnabled = filterItems.properties
    .find { /* 로컬 리뷰를 식별하는 조건, 예: it.category == FilterCategory.LOCAL_REVIEW */ }
    ?.let { tempFilterState.properties[it.id] == true } 
    ?: false
🤖 Prompt for AI Agents
In
app/src/main/java/com/spoony/spoony/presentation/explore/component/ExploreFilterSection.kt
around line 93, using properties.firstOrNull() to assume the first property is
the local review is fragile; instead locate the property by its category/type:
replace the firstOrNull() call with a search (e.g., find { it.category ==
FilterCategory.LOCAL_REVIEW } or whatever field identifies local review), then
check tempFilterState.properties[it.id] == true and fall back to false if not
found; ensure the enum FilterCategory.LOCAL_REVIEW is referenced correctly and
adjust null-safety accordingly.

Copy link
Collaborator

@Hyobeen-Park Hyobeen-Park left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

수고하셨습니다😊

@Roel4990 Roel4990 merged commit c69d657 into develop Nov 24, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

FEAT✨ 새로운 기능 구현 🧡세홍🧡 🧡세홍🧡

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 탐색 뷰에 믹스패널 붙이기

3 participants